﻿namespace Microsoft.SharePoint.Client
{
    using System;
    using System.IO;

    internal class TextPeekReader : TextReader
    {
        internal const int EOF = -1;
        private char[] m_buffer;
        private int m_bufferCount;
        private int m_bufferOffset;
        private int m_bufferSize;
        private int m_count;
        private TextReader m_reader;

        public TextPeekReader(TextReader reader)
        {
            this.m_bufferSize = 0x400;
            this.m_buffer = new char[this.m_bufferSize];
            this.m_reader = reader;
        }

        public TextPeekReader(TextReader reader, int bufferSize)
        {
            this.m_bufferSize = bufferSize;
            this.m_buffer = new char[this.m_bufferSize];
            this.m_reader = reader;
        }

        public override void Close()
        {
            base.Close();
            this.m_reader.Close();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                this.m_reader.Dispose();
            }
        }

        private void FillBuffer()
        {
            int num2;
            for (int i = this.m_bufferOffset; i < this.m_bufferCount; i++)
            {
                this.m_buffer[i - this.m_bufferOffset] = this.m_buffer[i];
            }
            this.m_bufferCount -= this.m_bufferOffset;
            this.m_bufferOffset = 0;
            while ((this.m_bufferCount < this.m_bufferSize) && ((num2 = this.m_reader.Read(this.m_buffer, this.m_bufferCount, this.m_bufferSize - this.m_bufferCount)) > 0))
            {
                this.m_bufferCount += num2;
            }
        }

        public override int Peek()
        {
            return this.Peek(0);
        }

        public int Peek(int position)
        {
            if (position > this.m_bufferSize)
            {
                throw new ArgumentOutOfRangeException("position");
            }
            if ((this.m_bufferOffset + position) < this.m_bufferCount)
            {
                return this.m_buffer[this.m_bufferOffset + position];
            }
            this.FillBuffer();
            if ((this.m_bufferOffset + position) < this.m_bufferCount)
            {
                return this.m_buffer[this.m_bufferOffset + position];
            }
            return -1;
        }

        public int Peek(char[] buffer, int count)
        {
            if (count > this.m_bufferSize)
            {
                throw new ArgumentOutOfRangeException("count");
            }
            int index = 0;
            while (((this.m_bufferOffset + index) < this.m_bufferCount) && (index < count))
            {
                buffer[index] = this.m_buffer[this.m_bufferOffset + index];
                index++;
            }
            if (count > index)
            {
                this.FillBuffer();
                while (((this.m_bufferOffset + index) < this.m_bufferCount) && (index < count))
                {
                    buffer[index] = this.m_buffer[this.m_bufferOffset + index];
                    index++;
                }
            }
            return index;
        }

        public override int Read()
        {
            int num;
            if (this.m_bufferOffset < this.m_bufferCount)
            {
                num = this.m_buffer[this.m_bufferOffset];
                this.m_bufferOffset++;
                this.m_count++;
                return num;
            }
            num = this.m_reader.Read();
            if (num != -1)
            {
                this.m_count++;
            }
            return num;
        }

        public int Read(char[] buffer, int count)
        {
            return this.Read(buffer, 0, count);
        }

        public override int Read(char[] buffer, int offset, int count)
        {
            int num2;
            int num = 0;
            while ((this.m_bufferOffset < this.m_bufferCount) && (num < count))
            {
                buffer[num + offset] = this.m_buffer[this.m_bufferOffset];
                num++;
                this.m_bufferOffset++;
                this.m_count++;
            }
            while ((num < count) && ((num2 = this.m_reader.Read(buffer, num + offset, count - num)) > 0))
            {
                num += num2;
                this.m_count += num2;
            }
            return num;
        }

        public int Skip()
        {
            return this.Skip(1);
        }

        public int Skip(int count)
        {
            int num = 0;
            while ((num < count) && (this.m_bufferOffset < this.m_bufferCount))
            {
                num++;
                this.m_bufferOffset++;
                this.m_count++;
            }
            if (num < count)
            {
                this.m_bufferOffset = 0;
                this.m_bufferCount = 0;
                do
                {
                    if (this.m_reader.Read() == -1)
                    {
                        return num;
                    }
                    num++;
                    this.m_count++;
                }
                while (num < count);
            }
            return num;
        }

        public int BufferSize
        {
            get
            {
                return this.m_bufferSize;
            }
        }

        public int Offset
        {
            get
            {
                return this.m_count;
            }
        }
    }
}

